'''
    Goblinoid: Experience all of MediaGoblin on an Android Device
    Copyright (C) 2015 Dylan Jeffers

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

from __future__ import print_function
from functools import partial

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.modalview import ModalView
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.properties import ObjectProperty, ListProperty,\
    StringProperty, NumericProperty

from goblinoid.services.media_service import MediaService
from goblinoid.services.login_service import remove_credential
from libs.toast.kivytoast import toast

Builder.load_file('screens/screenviews.kv')


class FeedView(Screen):
    data = ListProperty()

    def __init__(self, **kwargs):
        super(FeedView, self).__init__(**kwargs)
        self._pump_service = App.get_running_app().pump_service
        self.data = self._pump_service.feed_data


class FeedLayout(BoxLayout):
    index = NumericProperty()
    image_content = StringProperty()
    else_content = StringProperty()
    actor = StringProperty()
    post_time = ListProperty()
    description = StringProperty()
    comments = ListProperty()

    def __init__(self, **kwargs):
        super(FeedLayout, self).__init__(**kwargs)
        print('Added FeedLayout to FeedView')

    def on_comments(self, instance, comments):
        pass
        # print(comments[0])

    def open_comment_modal(self):
        activity = self.get_activity()
        comment_modal = CommentModalView(activity)
        comment_modal.open()

    def open_profile_modal(self):
        activity = self.get_activity()
        profile = activity.actor
        profile_modal = ProfileModalView(profile)
        profile_modal.open()

    def get_activity(self):
        return App.get_running_app().pump_service.inbox[self.index]


class FeedViewComments(BoxLayout):
    index = NumericProperty(None)
    comments = ListProperty()

    def on_comments(self, instance, comments):
        self.load_comments(comments)

    def load_comments(self, comments):
        print('loading comments')
        for comment in self.comments[:3]:
            label = CommentSnapshot(
                text=comment['content'])
            self.add_widget(label)

    def open_comment_modal(self):
        activity = self.get_activity()
        comment_modal = CommentModalView(activity)
        comment_modal.open()

    def get_activity(self):
        return App.get_running_app().pump_service.inbox[self.index]


class CommentSnapshot(Label):
    pass


class CommentModalView(ModalView):
    activity = ObjectProperty(None)
    comments = ListProperty()
    comment_layout = ObjectProperty(None)
    index = NumericProperty()

    def __init__(self, activity):
        super(CommentModalView, self).__init__()
        self.activity = activity
        try:
            self.comments = activity.obj.comments
        except AttributeError:
            print('no comments for PumpObject, will ignore for now...')
        self.comment_layout.bind(minimum_height=self.comment_layout.setter(
            'height'))

    def on_comments(self, instance, comments):
        self.build_comment_layout(comments)

    def build_comment_layout(self, comments):
        self.build_description_cell()
        for comment in comments:
            cell = CommentModalViewCell(comment)
            self.comment_layout.add_widget(cell)

    def build_description_cell(self):
        description_cell = ActivityDescriptionCell(self.activity)
        self.comment_layout.add_widget(description_cell)

    def post_comment(self, comment):
        pump_service = App.get_running_app().pump_service
        user_comment = pump_service.pump.Comment(comment)
        self.activity.obj.comment(user_comment)

# TODO reconcile these differences in feat/class_organization
#         # print (user_comment.author, user_comment.content)
#         # cell = CommentModalViewCell(user_comment)
#         # self.comment_layout.add_widget(cell)
# TODO is it best to pass the dict into the constructor?
        cell = CommentModalViewCell()
        cell.comment = dict([
            ("author", str(pump_service.pump.me)),
            ("content", comment)
            ])
        self.comment_layout.add_widget(cell)
        toast('comment uploaded', False)


class ActivityDescriptionCell(BoxLayout):
    activity = ObjectProperty(None)
    description = ObjectProperty(None)
    actor = ObjectProperty(None)

    def __init__(self, activity):
        super(ActivityDescriptionCell, self).__init__()
        self.activity = activity
# Note: currently handling Notes/Photo distinction this way
        self.description = activity.content
        self.actor = activity.actor


class CommentModalViewCell(BoxLayout):
    comment = ObjectProperty(None)

    def __init__(self, comment):
        super(CommentModalViewCell, self).__init__()
        self.comment = comment

    def open_profile_modal(self):
        profile = self.comment.author
        profile_modal = ProfileModalView(profile)
        profile_modal.open()


class ProfileView(Screen):
    profile = ObjectProperty(None)
    profile_modal = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(ProfileView, self).__init__(**kwargs)
        self.profile = App.get_running_app().pump_service.pump.me
        self.profile_modal = ProfileModalView(self.profile)
        self.profile_modal.open()
        print('profile: {0}'.format(self.profile))

    def on_profile(self, instance, profile):
        print('profile updated: {0}'.format(profile))

    def log_out(self):
        print(self.manager.pump_service.data_dir)
        self.profile_modal.dismiss()
        remove_credential(self.manager.pump_service.data_dir)
        App.get_running_app().open_view('login', True)


class MediaView(Screen):
    screen_box = ObjectProperty(None)
    msm = ObjectProperty(ScreenManager())
    # may evetually make media_service available to MediaView

    def __init__(self, **kwargs):
        super(MediaView, self).__init__(**kwargs)
        self.transition = SlideTransition(duration=.35)
        self.msm.media_service = MediaService()
        self.msm.transition = self.transition

    def on_enter(self):
        self.open_media_view('gallery', False)

    def open_media_view(self, name, previous):
        print('got to open_view: {0}, {1}'.format(name, previous))
        if self.msm.has_screen(name):
            self.msm.remove_widget(self.msm.get_screen(name))
        # grabs screen from dictionary of screens
        screen = self.msm.media_service.screen_dict[name](name=name)
        self.msm.add_widget(screen)
        if previous:
            self.transition.direction = 'right'
        else:
            self.transition.direction = 'left'
        self.msm.current = screen.name
        self.msm.current_screen.init_screen()

    def update_media_service(self, model):
        self.media_service = model


class ProfileModalView(ModalView):
    pump_service = ObjectProperty(None)
    profile = ObjectProperty(None)

    def __init__(self, profile):
        print('profile:{0}'.format(profile))
        super(ProfileModalView, self).__init__()
        self.pump_service = App.get_running_app().pump_service
        self.profile = profile

    def log_out(self):
        print('logging out...')
        remove_credential(self.pump_service.data_dir)
        App.get_running_app().open_view('login', True)


# this code is quite repetitive, and will be refactored eventually
class TabbedProfilePanel(TabbedPanel):
    profile = ObjectProperty(None)
    outbox = ObjectProperty(None)
    followers = ObjectProperty(None)
    following = ObjectProperty(None)

    activity_grid = ObjectProperty(None)
    follower_grid = ObjectProperty(None)
    following_grid = ObjectProperty(None)

    def on_profile(self, instance, profile):
        try:
            self.activity_grid.bind(minimum_height=self.activity_grid.setter(
                'height'))
            self.follower_grid.bind(minimum_height=self.follower_grid.setter(
                'height'))
            self.following_grid.bind(minimum_height=self.following_grid.setter(
                'height'))
            print('on profile')
            self.outbox = profile.outbox
            self.followers = profile.followers
            self.following = profile.following
        except KeyError, e:
            print('KeyError: {0}'.format(e))

    def on_outbox(self, instance, outbox):
        print('updating outbox')
        for activity in outbox[:10]:
            button = Button(
                text=str(activity),
                content=activity)
            self.activity_grid.add_widget(button)

    def on_followers(self, instance, followers):
        print('updating followers')
        for follower in followers[:10]:
            button = Button(
                text=str(follower),
                content=follower,
                on_release=partial(self.open_profile, follower))
            self.follower_grid.add_widget(button)

    def on_following(self, instance, following):
        print('updating following')
        for followee in following[:10]:
            button = Button(
                text=str(followee),
                content=followee,
                on_release=partial(self.open_profile, followee))
            self.following_grid.add_widget(button)

    def open_profile(self, followee, time):
        print('{0}, {1}'.format(followee, time))
        profile_modal = ProfileModalView(followee)
        profile_modal.open()


class ANote(Label):
    pass
